package com.loe.ui.view_other

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.webkit.JavascriptInterface
import androidx.annotation.Keep
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.widget.ViewPager2
import com.loe.mvp.ext_java.float
import com.loe.mvp.ext_java.safe
import com.loe.ui.*
import com.loe.ui.api.IUiView
import com.loe.ui.api.ViewApi
import com.loe.ui.page.UiPage
import com.quickjs.JSArray
import com.quickjs.JSFunction
import com.quickjs.JSObject
import com.zhpan.bannerview.BannerViewPager
import com.zhpan.bannerview.BaseBannerAdapter
import com.zhpan.bannerview.BaseViewHolder
import com.zhpan.bannerview.constants.IndicatorGravity
import com.zhpan.bannerview.constants.PageStyle
import com.zhpan.bannerview.transform.ScaleInTransformer
import com.zhpan.indicator.enums.IndicatorSlideMode
import com.zhpan.indicator.enums.IndicatorStyle

@Keep
@SuppressLint("AppCompatCustomView")
class UiBannerView : BannerViewPager<JSObject>, IUiView
{
    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    init
    {
        registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback()
        {
            override fun onPageSelected(i: Int)
            {
                onPageSelect?.invoke(i, data[i])
            }
        })
    }

    override val jsObject: JSObject by lazy {
        val view = this
        object : ViewApi(this)
        {
            @JavascriptInterface
            fun setItemConvert(callback: JSFunction)
            {
                view.setItemConvert()
                { holder, data ->
                    val i = holder.adapterPosition
                    callback.call(view.jsObject, JSArray(jsContext).push(jsObject).push(data).push(i))
                }
            }

            /** 元素点击 */
            @JavascriptInterface
            fun addOnItemClickListener(callback: JSFunction)
            {
                view.setOnPageClickListener()
                { clickedView, i ->
                    val data = data[i]
                    callback.call(jsObject, JSArray(jsContext).push(data).push(i))
                }
            }

            /** 设置列表 */
            @JavascriptInterface
            fun setDatas(array: JSArray)
            {
                view.refreshData(array.toList())
            }

            /** 获取列表 */
            @JavascriptInterface
            fun getDatas(): JSArray
            {
                val jsArray = JSArray(jsContext)
                data.forEach { jsArray.push(it) }
                return jsArray
            }

            /** 获取元素 */
            @JavascriptInterface
            fun get(i: Int): JSObject? = data[i]

            /** 移除元素 */
            @JavascriptInterface
            fun remove(i: Int)
            {
                data.removeAt(i)
                adapter.notifyItemRemoved(i)
            }

            /** 清除元素 */
            @JavascriptInterface
            fun clear()
            {
                data.clear()
                adapter.notifyDataSetChanged()
            }

            /** 元素选中 */
            @JavascriptInterface
            fun setOnPageSelect(callback: JSFunction)
            {
                onPageSelect = { i, data ->
                    callback.call(jsObject, JSArray(jsContext).push(data).push(i))
                }
            }
        }.jsObject
    }

    private var itemConvert: (UiPage.(holder: BaseViewHolder<JSObject>, data: JSObject) -> Unit)? = null

    /** 设置自定义Item处理 */
    fun setItemConvert(itemConvert: UiPage.(holder: BaseViewHolder<JSObject>, data: JSObject) -> Unit)
    {
        this.itemConvert = itemConvert
    }

    override fun setUI(ui: JSObject, uiPage: UiPage?): View
    {
        setInterval(ui.gotInt("interval", 6000))
        setScrollDuration(ui.gotInt("scrollDuration", 600))

        // autoPlay
        setAutoPlay(ui.gotBoolean("autoPlay", true))

        // canLoop
        ui.gotHasBoolean("canLoop") { setCanLoop(it) }

        // indicatorVisible
        ui.gotHasBoolean("indicatorVisible") { setIndicatorVisibility(if(it) VISIBLE else GONE) }
        // indicatorColor
        ui.gotHasString("indicatorColor")
        {
            val values = it.split(",")
            setIndicatorSliderColor(values[0].color, values[1].color)
        }
        // indicatorWidth
        ui.gotHasString("indicatorWidth")
        {
            val values = it.split(",")
            if (values.size == 1)
            {
                val d = values[0].px
                setIndicatorSliderWidth(d, d)
            } else
            {
                setIndicatorSliderWidth(values[0].px, values[1].px)
            }
        }

        // indicatorRadius
        ui.gotHasString("indicatorRadius")
        {
            val values = it.split(",")
            if (values.size == 1)
            {
                val d = values[0].px
                setIndicatorSliderRadius(d, d)
            } else
            {
                setIndicatorSliderRadius(values[0].px, values[1].px)
            }
        }
        // indicatorGap
        ui.gotHasString("indicatorGap") { setIndicatorSliderGap(it.px) }
        // indicatorHeight
        ui.gotHasString("indicatorHeight") { setIndicatorHeight(it.px) }
        // indicatorMargin
        ui.gotHasString("indicatorMargin")
        {
            val values = it.split(",")
            setIndicatorMargin(values[0].px, values[1].px, values[2].px, values[3].px)
        }
        // indicatorGravity
        ui.gotHasString("indicatorGravity")
        {
            setIndicatorGravity(when(it)
            {
                "start" -> IndicatorGravity.START
                "end" -> IndicatorGravity.END
                else -> IndicatorGravity.CENTER
            })
        }
        // indicatorMode
        setIndicatorSlideMode(
            when (ui.gotString("indicatorMode"))
            {
                "smooth" -> IndicatorSlideMode.SMOOTH
                "normal" -> IndicatorSlideMode.NORMAL
                "scale" -> IndicatorSlideMode.SCALE
                "color" -> IndicatorSlideMode.COLOR
                else -> IndicatorSlideMode.WORM
            }
        )
        // indicatorStyle
        setIndicatorStyle(
            when (ui.gotString("indicatorStyle"))
            {
                "circle" -> IndicatorStyle.CIRCLE
                "dash" -> IndicatorStyle.DASH
                else -> IndicatorStyle.ROUND_RECT
            }
        )

        // pageStyle
        ui.gotHasString("pageStyle")
        {
            val cs = it.split(",")
            val style = when (cs[0])
            {
                "multiOverlap" -> PageStyle.MULTI_PAGE_OVERLAP
                "multiScale" -> PageStyle.MULTI_PAGE_SCALE
                else -> PageStyle.NORMAL
            }
            val scale = if (cs.size > 1) cs[1].float else ScaleInTransformer.DEFAULT_MIN_SCALE
            setPageStyle(style, scale)
        }

        // revealWidth
        ui.gotHasString("revealWidth")
        {
            val values = it.split(",")
            if (values.size == 1)
            {
                val d = values[0].px
                setRevealWidth(d, d)
            } else
            {
                setRevealWidth(values[0].px, values[1].px)
            }
        }
        // pageMargin
        setPageMargin(ui.gotString("pageMargin", "0").px)


        // item
        val itemUI = ui.gotObject("item")

        adapter = object : BaseBannerAdapter<JSObject>()
        {
            override fun getLayoutId(viewType: Int) = R.layout.item_ui_full

            override fun bindData(holder: BaseViewHolder<JSObject>, data: JSObject, position: Int, pageSize: Int)
            {
                val page = holder.itemView as UiPage

                if (!page.hasUI) page.setUI(itemUI)
                itemConvert?.let { page.it(holder, data) }
            }
        }

        safe { setLifecycleRegistry((context as FragmentActivity).lifecycle) }

        // itemConvert
        ui.gotHasFunction("itemConvert")
        { callback ->
            setItemConvert()
            { holder, data ->
                val i = holder.adapterPosition
                callback.call(this@UiBannerView.jsObject, JSArray(jsContext).push(jsObject).push(data).push(i))
            }
        }

        // datas
        ui.gotHasArray("datas")
        {
            if (it.length() > 0)
            {
                val o = it.get(0)
                if (o is JSObject)
                {
                    refreshData(it.toList())
                } else
                {
                    val list = it.toList<String>().map { value -> JSObject(jsContext).set("value", value) }
                    refreshData(list)
                }
            } else
            {
                refreshData(ArrayList<JSObject>())
            }
        }

        create()

        return this
    }

    override var onSelect: (() -> Unit)? = null

    var onPageSelect: ((i: Int, data: JSObject) -> Unit)? = null
}